package concurrentpractice;

import com.google.common.collect.Lists;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;

/**
 * 之前两个解法是直接用的 Thread，这个加上 ThreadPool + Callable with return
 */
public class AtomicBooleanSolution {

  private AtomicBoolean isNumberPrinterEnable = new AtomicBoolean(true);

  @Test
  public void verifyAtomic() throws ExecutionException, InterruptedException {
    Callable<String> numberPrint = () -> {
      for (int i = 1; i < 52; i = i + 2) {
        while (!isNumberPrinterEnable.get()) {
          // waiting for numberPrinter be enabled.
        }
        for (int j = 0; j < 2; j++) {
          System.out.print(i + j);
        }
        isNumberPrinterEnable.set(false);
      }
      return "number print done";
    };
    Callable<String> letterPrint = () -> {
      for (char i = 'A'; i <= 'Z'; i++) {
        while (isNumberPrinterEnable.get()) {
          // waiting for letterPrinter be enabled.
        }
        System.out.print(i);
        isNumberPrinterEnable.set(true);
      }
      return "letter print done";
    };

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);

    // Executes the given tasks, returning a list of Futures holding their status and results when all complete.
    List<Future<String>> futures = fixedThreadPool
        .invokeAll(Lists.newArrayList(numberPrint, letterPrint));

    fixedThreadPool.shutdown();

    for (Future future : futures) {
      System.out.print("\n" + future.get());
    }
  }
}
